<?php

namespace App\Http\Controllers\Wechat;

use App\Http\Controllers\ClientController;
use App\Models\Common\Wechat;
use App\Models\ProxyMember;
use App\Models\Tools\Data;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class WechatPaySuccessController extends ClientController
{
    /**
     * 支付成功通知
     * @return mixed
     */
    public function index()
    {
        $app = Wechat::payment();
        $response = $app->handlePaidNotify(function ($message, $fail) use ($app) {
            try{
                DB::beginTransaction();

                // 查询订单信息（X锁）
                $order = DB::table('laifei_orders')
                    ->where('trade_no', '=', $message['out_trade_no'])
                    ->lockForUpdate()
                    ->first();
                $order = json_decode(json_encode($order), true);

                // 如果订单不存在 或者 订单已经支付过了
                if (!$order || !in_array($order['status'], Data::$laifeiOrderPrepay)) {
                    DB::rollBack();
                    return true; // 告诉微信，我已经处理完了或者订单没找到，别再通知我了
                }
                // 接收成功信息验证
                if ($message['return_code'] !== 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                    Log::info('订单支付失败:', ['$message' => $message, '$fail' => $fail]);
                    DB::rollBack();
                    return $fail('通信失败，请稍后再通知我');
                }

                // 调用微信的【订单查询】接口查该笔订单的情况，确认是已经支付
                $result = $app->order->queryByOutTradeNumber($order['trade_no']);
                if($result['return_code'] === 'FAIL'){ //通信失败
                    DB::rollBack();
                    return $fail('通信失败');
                }
                if(!isset($result['trade_state'])){ // 未查询到订单
                    DB::rollBack();
                    return $fail('未查询到订单');
                }
                if($result['trade_state'] === 'CLOSED'){ // 订单已关闭，不再通知
                    DB::rollBack();
                    return true;
                }
                if(!in_array($result['trade_state'], ['SUCCESS', 'NOPAY', 'PAYERROR'])){ //状态不可处理
                    DB::rollBack();
                    return $fail('未查询到订单');
                }

                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {
                    self::paySuccess($order);
                } elseif ($message['result_code'] === 'FAIL') {  // 用户支付失败
                    DB::table('laifei_orders')
                        ->where('order_id', '=', $order['order_id'])
                        ->update([
                            'status' => Data::DATA_DB_LAIFEI_ORDERS_STATUS_FAIL,
                        ]);
                }
                DB::commit();
                return true;
            }catch (\Exception $e){
                DB::rollBack();
                Log::emergency(WechatPaySuccessController::class, ['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
                return $fail('处理失败，已通知研发紧急处理');
            }
        });
        return $response;

    }

    public static function paySuccess($order)
    {
        // 支付成功，修改订单状态
        DB::table('laifei_orders')
            ->where('order_id', '=', $order['order_id'])
            ->update([
                'status' => Data::DATA_DB_LAIFEI_ORDERS_STATUS_SUCCESS,  // 支付成功
                'success_at' => date('Y-m-d H:i:s'),
            ]);

        // 处理订单信息：
        switch ($order['type']){
            case 1:// 如果是会员，修改会员状态
                // 查询当前是否已经是会员
                $vip_message = DB::table('laifei_vip')
                    ->where('we_id','=',$order['we_id'])
                    ->orderByDesc('vip_id')
                    ->get();
                $vip_message_arr = json_decode(json_encode($vip_message->toArray()), true);
                if(!$vip_message->count() ||($vip_message_arr[0] && $order['outer_id'] > $vip_message_arr[0]['vip_id']) ) {
                    // 首次开通会员 或 新购了高级会员，新建一个vip订单
                    $vc_id = DB::table('laifei_vip')->insertGetId([
                        'we_id' => $order['we_id'],
                        'vip_id' => $order['outer_id'],
                        'total_month' => 1,
                        'continue_times' => 1,
                        'start_time' => date('Y-m-d H:i:s'),
                        'end_time' => date('Y-m-d 23:59:59', strtotime('+1 month -1 day')),
                    ]);
                    DB::table('laifei_orders')
                        ->where('order_id', '=', $order['order_id'])
                        ->update([
                            'vc_id'=>$vc_id,
                            'start_date'=>date('Y-m-d H:i:s'),
                            'end_date'=>date('Y-m-d 23:59:59', strtotime('+1 month -1 day')),
                        ]);
                    // 首次开通会员自动分配一个专属顾问
                    // 查询we_id是否已有顾问
                    $has_adviser = DB::table('laifei_adviser_user')
                        ->where('we_id','=',$order['we_id'])
                        ->where('is_delete','=',0)
                        ->count();
                    if(!$has_adviser){//如果用户没有顾问，自动分配一个
                        // 查询一个顾问
                        $ad_id = DB::table('laifei_sys_adviser')
                            ->orderBy('service_count')
                            ->orderBy('ad_id')
                            ->limit(1)
                            ->sharedLock()
                            ->value('ad_id');
                        // 新增顾问记录
                        DB::table('laifei_adviser_user')->insertGetId([
                            'ad_id' => $ad_id,
                            'we_id' => $order['we_id'],
                        ]);
                        // 顾问已分配数自增
                        DB::table('laifei_sys_adviser')
                            ->where('ad_id','=',$ad_id)
                            ->increment('service_count');
                    }
                } else { // 已开通过会员,只允许续费高级会员
                    $vip_message_arr = $vip_message_arr[0];
                    $v_id = DB::table('laifei_vip')
                        ->where('we_id','=',$order['we_id'])
                        ->where('vip_id','=',$order['outer_id'])
                        ->value('v_id');
                    // 会员未到期续费
                    if(strtotime($vip_message_arr['end_time']) > strtotime(date('Y-m-d H:i:s'))){
                        DB::table('laifei_vip')
                            ->where('v_id','=',$v_id)
                            ->update([
                                'total_month' => ($vip_message_arr['total_month'] + 1),
                                'continue_times' => ($vip_message_arr['continue_times'] + 1),
                                'end_time' => date('Y-m-d 23:59:59',strtotime($vip_message_arr['end_time'].'+1 month')),
                            ]);
                        // 订单表处理：关联订单id和v_id，记录起止时间
                        DB::table('laifei_orders')
                            ->where('order_id', '=', $order['order_id'])
                            ->update([
                                'vc_id'=>$v_id,
                                'start_date'=>date('Y-m-d 00:00:00',strtotime($vip_message_arr['end_time'].'+1 second')),
                                'end_date'=>date('Y-m-d 23:59:59',strtotime($vip_message_arr['end_time'].'+1 month')),
                            ]);
                    } else { // 会员已到期续费
                        $v_message = $vip_message->where('vip_id','=',$order['outer_id'])->all();
                        $v_message = json_decode(json_encode($v_message), true);
                        $v_message = $v_message[0];
                        DB::table('laifei_vip')
                            ->where('v_id','=',$v_id)
                            ->update([
                                'total_month' => ($v_message['total_month']+1),
                                'continue_times' => 1,
                                'start_time' => date('Y-m-d H:i:s'),
                                'end_time' => date('Y-m-d 23:59:59',strtotime('+1 month')),
                            ]);
                        // 订单表处理：关联订单id和v_id，记录起止时间
                        DB::table('laifei_orders')
                            ->where('order_id', '=', $order['order_id'])
                            ->update([
                                'vc_id'=>$v_id,
                                'start_date'=>date('Y-m-d H:i:s'),
                                'end_date'=>date('Y-m-d 23:59:59', strtotime('+1 month -1 day')),
                            ]);
                    }
                }
                // 检查这个购买人是否有代理，以及推广时间，如果存在比例，那么需要给代理分成
                $apply_user = DB::table('lottery_users')->where('we_id','=',$order['we_id'])->first();
                $apply_user = json_decode(json_encode($apply_user), true);
                // 如果存在代理，计算返点:
                if(!is_null($apply_user['proxy'])){
                    $proportion = ProxyMember::proportion($apply_user['proxy_at']);
                    // 检查推荐时间，是否还有返利
                    if($proportion > 0){
                        // 增加余额:
                        // 查询黑卡价格
                        $vip_price = $order['total_fee'] * 100;
                        // 根据订单价格和返利比例，计算返利金额
                        $proxy_price = (int)floor($vip_price * $proportion);
                        DB::table('proxy_users')
                            ->where('we_id','=',$apply_user['proxy'])
                            ->increment('wallet',$proxy_price);
                        DB::table('proxy_log')->insert([
                            'type'=>1,
                            'proxy_we_id'=>$apply_user['proxy'],
                            'consumer_we_id'=>$order['we_id'],
                            'payment'=>$vip_price,
                            'proxy_price'=>$proxy_price,
                        ]);
                        // 给推荐人发送通知
                        ProxyMember::rebateNotice($apply_user['nickname'],$proxy_price,$apply_user['proxy']);
                    }
                }
                break;
            case 2:// 如果是课程，增加laifei_course表的课程信息
                $is_exist = DB::table('laifei_course')
                    ->where('we_id','=',$order['we_id'])
                    ->where('course_id','=',$order['outer_id'])
                    ->count();
                if(!$is_exist){
                    $c_id = DB::table('laifei_course')->insertGetId([
                        'we_id' => $order['we_id'],
                        'course_id' => $order['outer_id'],
                    ]);
                    // 关联订单id和c_id
                    DB::table('laifei_orders')
                        ->where('order_id', '=', $order['order_id'])
                        ->update([
                            'vc_id'=>$c_id,
                            'start_date'=>date('Y-m-d H:i:s'),
                        ]);
                    // 给课程的学习人数增加随机数
                    DB::table('laifei_sys_course')
                        ->where('course_id','=',$order['outer_id'])
                        ->increment('learning_num',rand(1,9));
                }else{
                    Log::emergency(WechatPaySuccessController::class, ['errMsg'=>'购买了重复课程','order'=>$order]);
                }
                // 检查这个购买人是否有代理，以及推广时间，如果存在比例，那么需要给代理分成
                $apply_user = DB::table('lottery_users')->where('we_id','=',$order['we_id'])->first();
                $apply_user = json_decode(json_encode($apply_user), true);
                // 如果存在代理，计算返点:
                if(!is_null($apply_user['proxy'])){
                    $proportion = ProxyMember::proportion($apply_user['proxy_at']);
                    // 检查推荐时间，是否还有返利
                    if($proportion > 0){
                        // 增加余额:
                        // 查询黑卡价格
                        $vip_price = $order['total_fee'] * 100;
                        // 根据订单价格和返利比例，计算返利金额
                        $proxy_price = (int)floor($vip_price * $proportion);
                        DB::table('proxy_users')
                            ->where('we_id','=',$apply_user['proxy'])
                            ->increment('wallet',$proxy_price);
                        DB::table('proxy_log')->insert([
                            'type'=>2,
                            'proxy_we_id'=>$apply_user['proxy'],
                            'consumer_we_id'=>$order['we_id'],
                            'payment'=>$vip_price,
                            'proxy_price'=>$proxy_price,
                        ]);
                        // 给推荐人发送通知
                        ProxyMember::rebateNotice($apply_user['nickname'],$proxy_price,$apply_user['proxy']);
                    }
                }
                break;
            case 3:
                // 查询当前客户是否有探店存量（包括为0）
                $r_id = DB::table('explore_remaining')
                    ->where('we_id','=',$order['we_id'])
                    ->where('channel_id','=',$order['outer_id'])
                    ->lockForUpdate()
                    ->value('r_id');
                if($r_id){
                    // 有曾经的记录，修改数量
                    DB::table('explore_remaining')
                        ->where('r_id','=',$r_id)
                        ->increment('remaining_times',$order['num']);
                    $remaining = DB::table('explore_remaining')->where('r_id','=',$r_id)->first();
                    $rest_num = $remaining->remaining_times;
                    $in_use_times = $remaining->in_use_times;
                } else {
                    // 没有记录，新增记录
                    $r_id = DB::table('explore_remaining')->insertGetId([
                        'we_id' => $order['we_id'],
                        'channel_id' => $order['outer_id'],
                        'remaining_times' => $order['num'],
                    ]);
                    $rest_num = $order['num'];
                }
                // 记录操作日志
                $log_id = DB::table('explore_remaining_log')->insertGetId([
                    'r_id'=>$r_id,
                    'action'=>Data::DATA_DB_EXPLORE_REMAINING_LOG_TYPE_RECHARGE,//充值
                    'action_num'=>$order['num'],
                    'rest_num'=>$rest_num,
                    'in_use_num'=>$in_use_times ?? 0,
                ]);
                // 将操作日志记录绑定到订单的vc_id
                DB::table('laifei_orders')
                    ->where('order_id','=',$order['order_id'])
                    ->update([
                        'vc_id'=>$log_id,
                    ]);
                break;
            case 4:
                // 查询当前客户是否有探店存量（包括为0）
                $lr_id = DB::table('lottery_remaining')
                    ->where('we_id','=',$order['we_id'])
                    ->where('st_id','=',$order['outer_id'])
                    ->lockForUpdate()
                    ->value('lr_id');
                if($lr_id){
                    // 有曾经的记录，修改数量
                    DB::table('lottery_remaining')
                        ->where('lr_id','=',$lr_id)
                        ->increment('remaining_times',$order['num']);
                    $remaining = DB::table('lottery_remaining')->where('lr_id','=',$lr_id)->first();
                    $rest_num = $remaining->remaining_times;
                    $in_use_times = $remaining->in_use_times;
                } else {
                    // 没有记录，新增记录
                    $lr_id = DB::table('lottery_remaining')->insertGetId([
                        'we_id' => $order['we_id'],
                        'st_id' => $order['outer_id'],
                        'remaining_times' => $order['num'],
                    ]);
                    $rest_num = $order['num'];
                }
                // 记录操作日志
                $log_id = DB::table('lottery_remaining_log')->insertGetId([
                    'lr_id'=>$lr_id,
                    'action'=>1,//充值
                    'action_num'=>$order['num'],
                    'rest_num'=>$rest_num,
                    'in_use_num'=>$in_use_times ?? 0,
                ]);
                // 将操作日志记录绑定到订单的vc_id
                DB::table('laifei_orders')
                    ->where('order_id','=',$order['order_id'])
                    ->update([
                        'vc_id'=>$log_id,
                    ]);
                break;
        }
    }

}
